using System;
using System.Collections.Generic;
using System.Text;
using Cartography.Desktop;

namespace GPS
{
    class NMEAParser
    {
        /*
        $GPRMC,123519,A,4807.038,N,01131.000,E,022.4,084.4,230394,003.1,W*6A

        Where:
             RMC          Recommended Minimum sentence C
             123519       Fix taken at 12:35:19 UTC
             A            Status A=active or V=Void.
             4807.038,N   Latitude 48 deg 07.038' N
             01131.000,E  Longitude 11 deg 31.000' E
             022.4        Speed over the ground in knots
             084.4        Track angle in degrees True
             230394       Date - 23rd of March 1994
             003.1,W      Magnetic Variation
             *6A          The checksum data, always begins with *
         */
        public static GPSData parseFromRMC(string NMEASentence)
        {
            string[] tokens = NMEASentence.Split(',');

            GPSData gpsData = new GPSData();


            gpsData.time = float.Parse(tokens[1]);
            //shall we add the A=active or V=Void flag?
            /* amonares 23/11/2007 */
            gpsData.valida = (tokens[2] == "A" && isValidSentence(NMEASentence));
            if (gpsData.valida)
            {
                // --------------------------- esto fue modificado -------------------------
                int degreesLat = int.Parse(tokens[3].Substring(0, 2));
                double minutesLat;
                String coordLat = tokens[3].Substring(2);
                int idxComaLat = coordLat.IndexOf(",");
                int idxPuntoLat = coordLat.IndexOf(".");
                if (idxComaLat < 0 && idxPuntoLat < 0)
                    minutesLat = Double.Parse(coordLat);
                else
                {
                    if (idxComaLat < 0)
                        idxComaLat = idxPuntoLat;
                    String pEntera = coordLat.Substring(0, idxComaLat);
                    String pDecimal = coordLat.Substring(idxComaLat + 1);
                    String mantisaS = pEntera + pDecimal;
                    double mantisa = Double.Parse(mantisaS);
                    double exp = pDecimal.Length;
                    minutesLat = mantisa * Math.Pow(10, -exp);
                }

                double lat = (Math.Abs(degreesLat) + minutesLat / 60) * Math.Sign(degreesLat);

                int degreesLon = int.Parse(tokens[5].Substring(0, 3));
                double minutesLon;
                String coordLon = tokens[5].Substring(3);
                int idxComaLon = coordLon.IndexOf(",");
                int idxPuntoLon = coordLon.IndexOf(".");
                if (idxComaLon < 0 && idxPuntoLon < 0)
                    minutesLon = Double.Parse(coordLon);
                else
                {
                    if (idxComaLon < 0)
                        idxComaLon = idxPuntoLon;
                    String pEntera = coordLon.Substring(0, idxComaLon);
                    String pDecimal = coordLon.Substring(idxComaLon + 1);
                    String mantisaS = pEntera + pDecimal;
                    double mantisa = Double.Parse(mantisaS);
                    double exp = pDecimal.Length;
                    minutesLon = mantisa * Math.Pow(10, -exp);
                }

                double lon = (Math.Abs(degreesLon) + minutesLon / 60) * Math.Sign(degreesLon);

                if (tokens[4] == "S") lat = -lat;
                if (tokens[6] == "W") lon = -lon;

                gpsData.coords = new LatLon(lat, lon);
                // ------------------hasta aki---------------------------------------------
                /*gpsData.latitude = new Latitude(tokens[3]);

                gpsData.latitude.direction(tokens[4] == "N" ? 1 : -1);

                gpsData.longitude = new Longitude(tokens[5]);

                gpsData.longitude.direction(tokens[6] == "E" ? 1 : -1);

                /*gpsData.latitude = float.Parse(tokens[3]);
                gpsData.latitude *= (tokens[4] == "N" ? 1 : -1);
                gpsData.longitude = float.Parse(tokens[5]);
                gpsData.longitude *= (tokens[6] == "E" ? 1 : -1);*/

                gpsData.speed = tokens[7] == "" ? 0 : float.Parse(tokens[7]);
                gpsData.date = uint.Parse(tokens[9]);
            }
            return gpsData;
        }

        public static bool isValidSentence(string NMEASentence)
        {
            int idx = NMEASentence.IndexOf("*");
            string s = NMEASentence.Substring(1, idx-1);
            string checksum = NMEASentence.Substring(idx + 1, 2);

            //MessageBox.Show(s + "\n" + checksum);

            int sum = 0;
            for (int i = 0; i < s.Length; i++)
                sum = sum ^ (int)(s[i]);
            
            //MessageBox.Show(s + "\n" + checksum + "\n" + string.Format("{0:X2}", sum));
            return (checksum == string.Format("{0:X2}", sum));
        }
    }
}
